package com.elitel.frame.main.common.datasource;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.druid.filter.stat.StatFilter;
import com.elitel.frame.core.util.ApplicationContextHelper;
import com.elitel.frame.main.config.properties.DynamicDatasourceProperties;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;


/**
 * Druid数据源
 * @create fwq
 * @update
 * @updateDate
 */
//@Slf4j
public class DruidDynamicDataSource extends AbstractDynamicDataSource<DruidDataSource> {

    // 配置监控统计拦截的filters
    private String filters; // 监控统计："stat" 防SQL注入："wall" 组合使用： "stat,wall"
    private List<Filter> filterList;

    /*
     * 创建数据源
     */
    @Override
    public DruidDataSource createDataSource(String driverClassName, String url, String username,
                                            String password){
        DynamicDatasourceProperties configProperties = (DynamicDatasourceProperties) ApplicationContextHelper.getApplicationContext().getBean("dynamicDatasourceProperties");
        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setDriverClassName(driverClassName);
        if ("oracle.jdbc.driver.OracleDriver".equals(driverClassName)) {
            ds.setValidationQuery("SELECT 1 FROM DUAL");
            //处理从MetaData读取备注为空
            ds.getConnectProperties().setProperty("remarks", "true");
        } else if ("org.hsqldb.jdbcDriver".equals(driverClassName)){
            ds.setValidationQuery("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS");
        } else {
            ds.setValidationQuery("SELECT 1");
        }

        // here is from config dynamicDataSourceProperteis
        ds.setInitialSize(configProperties.getInitialSize());
        ds.setMinIdle(configProperties.getMinIdle());
        ds.setMaxActive(configProperties.getMaxActive());
        ds.setMaxWait(configProperties.getMaxWaitTime());
        ds.setQueryTimeout(configProperties.getQueryTimeout());
        ds.setTimeBetweenConnectErrorMillis(configProperties.getTimeBetweenConnectErrorMillis());
        ds.setTimeBetweenEvictionRunsMillis(configProperties.getTimeBetweenEvictionRunsMills());
        ds.setMinEvictableIdleTimeMillis(configProperties.getMinEvictableIdleTimeMillis());
        ds.setMaxEvictableIdleTimeMillis(configProperties.getMaxEvictableIdleTimeMillis());

        ds.setTestWhileIdle(configProperties.isTestWhileIdle());
        ds.setTestOnBorrow(configProperties.isTestOnBorrow());
        ds.setTestOnReturn(configProperties.isTestOnReturn());

        ds.setKeepAlive(configProperties.isKeepAlive());

        // here not find config <property name="keepAliveBetweenTimeMillis" value="30000" />  <!--The default value of keepalive interval is 120000. Unit: milliseconds. -->
        ds.setRemoveAbandoned(configProperties.isRemoveAbandoned());
        ds.setRemoveAbandonedTimeoutMillis(configProperties.getRemoveAbandonedTimeoutMillis());
        ds.setLogAbandoned(configProperties.isLogAbandoned());

        // 只要maxPoolPreparedStatementPerConnectionSize>0,poolPreparedStatements就会被自动设定为true，参照druid的源码
        ds.setMaxPoolPreparedStatementPerConnectionSize(configProperties.getMaxPoolPreparedStatementPerConnectionSize());


        // Druid监控配置, 人大金仓不支持
//        try {
//            ds.setFilters("stat,wall");
//        }catch (Exception e){
//            e.printStackTrace();
//        }
        List<Filter> list = new ArrayList<>();
        StatFilter statfilter = new StatFilter();
//        statfilter.setMergeSql(true);
        statfilter.setMergeSql(false);
        statfilter.setSlowSqlMillis(5000);
        statfilter.setLogSlowSql(true);
        list.add(statfilter);
        ds.setProxyFilters(list);

        if (StringUtils.isNotBlank(filters))
            try {
                ds.setFilters(filters);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

        addFilterList(ds);
        return ds;
    }

    private void addFilterList(DruidDataSource ds) {
        if (filterList != null) {
            List<Filter> targetList = ds.getProxyFilters();
            for (Filter add : filterList) {
                boolean found = false;
                for (Filter target : targetList) {
                    if (add.getClass().equals(target.getClass())) {
                        found = true;
                        break;
                    }
                }
                if (!found)
                    targetList.add(add);
            }
        }
    }
}
